/**
 * request 网络请求工具
 * 更详细的 api 文档: https://github.com/umijs/umi-request
 */
import { extend } from 'umi-request';
import { notification } from 'antd';
import react from 'react';

const TIMEOUT = 3000;
const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

/**  异常处理程序  */
const errorHandler = error => {
  const { response } = error;
  if (response && response.status) {
    const { status, url } = response;
    const errorText = codeMessage[status] || response.statusText;
    notification.error({ message: `请求错误 ${status}: ${url}`, description: errorText });
  } else if (!response) {
    notification.error({ message: '网络异常', description: '您的网络发生异常，无法连接服务器' })
  };
  return response;
};

const commonRequest = extend({
  errorHandler,                    // 默认错误处理
  credentials: 'include',          // 默认请求是否带上cookie
  headers: { ACJSESSIONID: sessionStorage.getItem('ACJSESSIONID') },
  params: { _channelType: 'ajax' },
  maxCache: 100,                   // 最大缓存个数, 超出后会自动清掉按时间最开始的一个
  timeout: TIMEOUT,
  requestType: 'form',
  // prefix: apiPath,              //前缀
  // suffix: '.json',              //后缀, 比如某些场景 api 需要统一加 .json
});
// export default commonRequest;

let errCount = 0;
const request = (url, config) =>
  new Promise((resolve, reject) => {
    commonRequest(url, config).then(res => {
      if (3 > 2 || res.code === 0) {
        resolve(res);
        return;
      }
      if (errCount === 0) {
        errCount++;
        notification.error({
          message: `错误码 ${res.code}`,
          description: (
            <>
              {res.errMessage}
              {res.code === 'SESSION_ERROR' ?
                <a onClick={() => { router.push(`/user/login?redirect=${window.location.href}`); }} >跳转至登录页</a>
                : ''}
            </>
          ),
          onClose: () => errCount--,
        });
        resolve(res);
      }
    });
  });

export default request;

// 安装
// npm install umi-request --save

// request options 参数
// 参数	                          说明	类型	可选值	默认值
// method	                       请求方式	string	get , post , put ...	get
// params	                       url请求参数	object	--	--
// charset	                     字符集	string	utf8 , gbk	utf8
// requestType	                 post请求时数据类型	string	json , form	json
// data 	                       提交的数据	any	--	--
// responseType	                 如何解析返回的数据	string	json , text , blob , formData ...	json , text
// getResponse	                 是否获取源response, 返回结果将包裹一层	boolean	--	fasle
// timeout	                     超时时长, 默认毫秒, 写操作慎用	number	--	--
// useCache	                     是否使用缓存（仅支持浏览器客户端）	boolean	--	false
// ttl	                         缓存时长, 0 为不过期	number	--	60000
// prefix	                       前缀, 一般用于覆盖统一设置的prefix	string	--	--
// suffix	                       后缀, 比如某些场景 api 需要统一加 .json	string	--	--
// errorHandler	                 异常处理, 或者覆盖统一的异常处理	function(error)	--
// headers	                     fetch 原有参数	object	--	{}
// credentials	                 fetch 请求包含 cookies 信息	object	--	credentials: 'include'
// parseResponse	               是否对 response 做处理简化	boolean	--	true
// throwErrIfParseFail	         当 responseType 为 'json', 对请求结果做 JSON.parse 出错时是否抛出异常	boolean	--	false
// cancelToken	                 取消请求的 Token	CancelToken.token	--	--
// type	                         请求类型，normal 为 fetch	string	--	normal
// fetch                         原其他参数有效, 详见fetch文档

// extend options 初始化默认参数, 支持以上所有
// 参数	                          说明	类型	默认值
// maxCache	                     最大缓存数	number	不限
// prefix	                       默认url前缀	string	--
// errorHandler	                 默认异常处理	function(error)	--
// headers	                     默认headers	object	{}
// params	                       默认带上的query参数	object	{}
// ...

// import request, { extend } from 'umi-request';
// /**
//  * 这里介绍四种处理方式
//  */
// /**
//  * 1. 统一处理
//  * 常用于错误码较规范的项目中, 集中处理错误.
//  */
//
// const codeMap = {
//   '021': '发生错误啦',
//   '022': '发生大大大大错误啦',
//   ...
// };
//
// const errorHandler = (error) => {
//   const { response, data } = error;
//   message.error(codeMap[data.errorCode]);
//
//   throw error;   // 如果throw. 错误将继续抛出.
//   // return {some: 'data'}; 如果return, 将值作为返回. 不写则相当于return undefined, 在处理结果时判断response是否有值即可.
// }
//
// const extendRequest = extend({
//   prefix: server.url,
//   errorHandler
// });
//
// const response = await extendRequest('/some/api'); // 将自动处理错误, 不用catch. 如果throw了需要catch.
// if (response) {
//   // do something
// }
//
// /**
//  * 2. 单独特殊处理
//  * 如果配置了统一处理, 但某个api需要特殊处理. 则在请求时, 将errorHandler作为参数传入.
//  */
// const response = await extendRequest('/some/api', {
//   method: 'get',
//   errorHandler: (error) => {
//     // do something
//   }
// });
//
// /**
//  * 3. 不配置 errorHandler, 将reponse直接当promise处理, 自己catch.
//  */
// try {
//   const response = await request('/some/api');
// } catch (error) {
//   // do something
// }
//
// /**
//  * 4. 基于response interceptors
//  */
// request.interceptors.response.use((response) => {
//   const codeMaps = {
//     502: '网关错误。',
//     503: '服务不可用，服务器暂时过载或维护。',
//     504: '网关超时。',
//   };
//   message.error(codeMaps[response.status]);
//   return response;
// });
//
// /**
//  * 5. 对于状态码实际是 200 的错误
//  */
// request.interceptors.response.use(async (response) => {
//   const data = await response.clone().json();
//   if(data && data.NOT_LOGIN) {
//     location.href = '登录url';
//   }
//   return response;
// })
//
//

// ---------------------      分割线      -------------------------------------

// import Constants from '../../config/Constants.config';
// import {message} from 'antd';
//
//
// import Ajax from 'robe-ajax';
// const timeout = 30000;//30秒
// const errCount = 0;
//
// export default function request(url, options) {
//   options.data = { ...options.data, _channelType: 'ajax' };
//   let res = {
//     url,
//     method: 'get',
//     timeout,
//     data: {},
//     dataType: 'JSON',
//     headers: { [Constants.ACJSESSIONID]: sessionStorage.getItem(Constants.ACJSESSIONID) },
//     traditional: true,
//     xhrFields: {
//       withCredentials: true
//     },
//     ...options
//   };
//   return Ajax.ajax(res).then(data => {
//     if (data.code !== "ok") {
//       message.error(data.errMessage);
//       if (data.code === 'SESSION_ERROR') {
//         setTimeout(() =>
//             document.location.href = "/login"
//           , 1000);
//       }
//     }
//     return { data };
//   }).catch(err => {
//     err.abort();//终止请求
//     message.error("服务器连接失败");
//   });
// }

// export function requestString(url, options) {
//     options.data[Constants.CHANNEL_TYPE] = Constants.AJAX;
//     let res = {
//         url,
//         method: 'get',
//         timeout,
//         data: "",
//         contentType: "application/json",
//         dataType: 'JSON',
//         headers: { [Constants.ACJSESSIONID]: sessionStorage.getItem(Constants.ACJSESSIONID) },
//         xhrFields: {
//             withCredentials: true
//         },
//         ...options
//     };
//     res.data = JSON.stringify(options.data);
//     return Ajax.ajax(res).then(data => {
//         if (data.code !== "ok") {
//             message.error(data.errMessage);
//             if (data.code === 'SESSION_ERROR') {
//                 setTimeout(() =>
//                     document.location.href = "/login"
//                 , 1000);
//             }
//         }
//         return { data };
//     }).catch(err => {
//         err.abort();//终止请求
//         message.error("服务器连接失败");
//     });
// }

//------------------------------------ todo contentType  HTTP content-type -------------------------------------------------------
// 常见的媒体格式类型如下：
// text/plain                                            纯文本格式
// text/html                                             HTML格式
// text/xml                                              XML格式
// image/gif                                             gif图片格式
// image/jpeg                                            jpg图片格式
// image/png                                             png图片格式

// 以application开头的媒体格式类型：
// application/xhtml+xml                                 XHTML格式
// application/xml                                       XML数据格式
// application/atom+xml                                  Atom XML聚合格式
// application/json                                      JSON数据格式
// application/pdf                                       pdf格式
// application/msword                                    Word文档格式
// application/octet-stream                              二进制流数据（如常见的文件下载）
// application/x-www-form-urlencoded;charset="utf-8"     todo <form encType=””>中默认的encType，form表单数据被编码为key/value格式发送到服务器（表单默认的提交数据的格式）
//                                                       是最常用的一种请求编码方式，支持GET/POST等方法，所有数据变成键值对的形式 key1=value1&key2=value2
//                                                       的形式，并且特殊字符需要转义成utf-8编号，如空格会变成 %20;
// application/json;charset=utf-8                        todo 消息主体是序列化后的 JSON 字符串（JSON.stringify(参数)）,这个类型越来越多地被大家所使用

// 另外一种常见的媒体格式是上传文件之时使用的：
// multipart/form-data                                   todo 需要在表单中进行文件上传时，就需要使用该格式
